package com.pig4cloud.pigx.strategy.executor.contract.order.supporter;

import com.pig4cloud.pigx.common.customize.contants.BigDecimalConstants;
import com.pig4cloud.pigx.common.customize.contants.SystemConfigConstants;
import com.pig4cloud.pigx.common.customize.utils.BigDecimalUtils;
import com.pig4cloud.pigx.strategy.util.StrategyContractUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

/**
 * 策略-合约计算器
 *
 * @since 2022/11/28 20:03
 */
public class StrategyOrderContractCalculator {

    /**
     * 订单面值
     * <p> 订单面值 = 价格 * 持仓张数 * 张数面值
     *
     * @param price      价格
     * @param num        持仓张数
     * @param sheetValue 张数面值
     * @return {@link BigDecimal}
     * @since 2022/11/30 20:44
     */
    public static BigDecimal orderValue(BigDecimal price,
                                        Integer num,
                                        BigDecimal sheetValue) {

        return price.multiply(BigDecimal.valueOf(num))
                .multiply(sheetValue);

    }

    /**
     * 标准保证金
     * <p> 标准保证金 = 订单面值 / 杠杆倍数
     *
     * @param orderValue 订单面值
     * @param multiple   杠杆倍数
     * @return {@link BigDecimal}
     * @since 2022/11/30 20:49
     */
    public static BigDecimal standardMargin(BigDecimal orderValue, BigDecimal multiple) {
        return orderValue.divide(multiple, 8, RoundingMode.HALF_UP);
    }

    /**
     * 收益
     * <p> 收益 =（当前价格 - 持仓均价） * 方向（多1、空-1） * 持仓量 * 张数面值
     *
     * @param side       方向
     * @param price      价格
     * @param openAvg    开仓均价
     * @param nowNum     当前持仓数量
     * @param sheetValue 张数面值
     * @return {@link BigDecimal}
     * @since 2022/11/30 20:51
     */
    public static BigDecimal profit(String side,
                                    BigDecimal price,
                                    BigDecimal openAvg,
                                    Integer nowNum,
                                    BigDecimal sheetValue) {

        if (nowNum == 0) {
            return BigDecimal.ZERO;
        }

        BigDecimal sideValue = StrategyContractUtil.getSideValue(side);

        return price.subtract(openAvg)
                .multiply(sideValue)
                .multiply(BigDecimal.valueOf(nowNum))
                .multiply(sheetValue)
                .setScale(SystemConfigConstants.amountScale, SystemConfigConstants.mainCurRoundingMode);

    }

    /**
     * 收益率
     * <p> 收益率 = 盈亏 / 保证金
     *
     * @param profit 收益
     * @param margin 保证金
     * @return {@link BigDecimal}
     * @since 2022/11/30 20:58
     */
    public static BigDecimal profitRate(BigDecimal profit,
                                        BigDecimal margin) {

        if (profit.compareTo(BigDecimal.ZERO) == 0 || margin.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }

        return profit.divide(margin, 4, RoundingMode.HALF_UP)
                .movePointRight(2);

    }

    /**
     * 手续费
     * <p> 手续费 = 订单面值 * 手续费率
     *
     * @param orderValue      订单面值
     * @param handlingFeeRate 手续费率
     * @return {@link BigDecimal}
     * @since 2022/11/30 20:49
     */
    public static BigDecimal handlingFee(BigDecimal orderValue, BigDecimal handlingFeeRate) {
        return orderValue.multiply(BigDecimalUtils.toPercent(handlingFeeRate));
    }

    /**
     * 计算平均价格
     *
     * @param oldAvgPrice 旧平均价格
     * @param oldNum      旧数量
     * @param price       价格
     * @param num         数量
     * @return {@link BigDecimal}
     * @since 2022/9/2 21:33
     */
    public static BigDecimal dealAvg(BigDecimal oldAvgPrice,
                                     int oldNum,
                                     BigDecimal price,
                                     int num) {
        // 旧平均价格、旧数量为空，赋默认值
        if (Objects.isNull(oldAvgPrice)) {
            oldAvgPrice = BigDecimal.ZERO;
        }
        if (Objects.isNull(oldNum)) {
            oldAvgPrice = BigDecimal.ZERO;
        }

        BigDecimal oldValue = oldAvgPrice.multiply(BigDecimal.valueOf(oldNum));
        BigDecimal newValue = price.multiply(BigDecimal.valueOf(num));
        BigDecimal totalValue = oldValue.add(newValue);
        BigDecimal totalNum = BigDecimal.valueOf(oldNum + num);

        if (totalNum.compareTo(BigDecimal.ZERO) <= 0) {
            throw new RuntimeException("数据异常，数量小于等于0");
        }

        // 根据总价值除以总数量，得出平均价格
        return totalValue.divide(totalNum, SystemConfigConstants.amountScale, SystemConfigConstants.mainCurRoundingMode);
    }

}
